package org.lisy.java.thread;

import java.util.concurrent.Exchanger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * 交换者
 * 
 * @author lisy
 */
public class ExchangerOperate {

	/**
	 * exchange(V x): 两个线程通过 exchange 方法交换数据， 如果第一个线程先执行 exchange 方法，它会一直等待第二个线程也执行 exchange，当两个线程都到达同步点时，这两个线程就可以交换数据，将本线程生产出来的数据传递给对方 
	 * exchange(V x,long timeout,TimeUnit unit): 可以设置最大等待时间
	 */
    public static void main(String[] args) {
        ExecutorService executor = Executors.newCachedThreadPool();
        final Exchanger<String> exchanger = new Exchanger<String>();
        executor.execute(new Runnable() {
            String data = "No.1";
            @Override
            public void run() {
                trade(data, exchanger);
            }
        });

        executor.execute(new Runnable() {
            String data = "No.2";
            @Override
            public void run() {
            	trade(data, exchanger);
            }
        });

        executor.execute(new Runnable() {
            String data = "No.3";

            @Override
            public void run() {
            	trade(data, exchanger);
            }
        });

        executor.execute(new Runnable() {
            String data = "No.4";

            @Override
            public void run() {
            	trade(data, exchanger);
            }
        });

        executor.shutdown();
    }

    private static void trade(String outData, Exchanger<String> exchanger) {
        try {
            System.out.println(Thread.currentThread().getName() + " before exchange " + outData);
            TimeUnit.SECONDS.sleep((long) (Math.random() * 1 + 1));
            String inData = (String) exchanger.exchange(outData);
            System.out.println(Thread.currentThread().getName() + " after exchange " + inData);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
	
}
